#! /usr/bin/env python
# -*- coding: utf-8 -*-

"""
Reads the commands from the orth_canavas module and plots the orthographic 
diagram via pyCairo and save it to a file.
"""

from math import pi, sqrt

def plot_diagram(Comands, file_name, size = [200,100], title='', comments='', 
            count=0, density=None, dsize=None, d_max_value=None ,
                    isolines=True, pdensity=True, isblank=False, whitespaces=1.4):
    height, width = size[1]*whitespaces, size[0]*whitespaces  
    cx, cy = width/2, height/2
    
    import cairo
    
    surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, int(width), int(height))
    ctx = cairo.Context(surface)
    
    ctx.set_source_rgb (1, 1, 1)
    ctx.set_operator (cairo.OPERATOR_SOURCE)
    ctx.paint()
    
    if density:
        if pdensity: plot_density(density, ctx, size[0], size[1], cx, cy, 
                                  dsize, d_max_value)
        if isolines: plot_isolines(density, dsize, size[0], size[1], cx, cy, ctx)
        

    draw_Frame(ctx, size[0], size[1], cx, cy)
    
    for cmds in Comands:
        for cmd in cmds:
            if cmd[0] == 'point':
                x, y = recalc_coords(cmd[1][0], cmd[1][1], size[0], size[1], cx, cy)
                draw_Point(ctx, x, y, cmd[2])            
            if cmd[0] == 'line':
                x1, y1 = recalc_coords(cmd[1][0], cmd[1][1], size[0], size[1], cx, cy)
                x2, y2 = recalc_coords(cmd[1][2], cmd[1][3], size[0], size[1], cx, cy)
                draw_Line(ctx, x1, y1, x2, y2, cmd[2])            
            else:
                import sys
                sys.stderr.write('WARNING! Cannot recognize %s method\n' %
                                                                        cmd[0]) 
    if not isblank:        
        # show annotation text
        ctx.set_source_rgb (0, 0, 0)
        ctx.set_line_width (0.5)
        ctx.select_font_face("Arial", 
                    cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
        ctx.set_font_size(12)
        
        ctx.move_to(cx-size[0]/2-20,cy-size[1]/2); ctx.show_text('0')
        ctx.move_to(cx-size[0]/2-20,cy)          ; ctx.show_text('90')    
        ctx.move_to(cx-size[0]/2-20,cy+size[1]/2); ctx.show_text('0')
        
        ctx.move_to(cx-size[0]/2,cy-size[1]/2-2); ctx.show_text('0')
        ctx.move_to(cx+size[0]/2,cy-size[1]/2-2); ctx.show_text('360')
        ctx.stroke()
        
        # show title
        ctx.set_source_rgb (0, 0, 0)
        ctx.set_line_width (0.5)
        ctx.select_font_face("Arial", 
                    cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
        ctx.set_font_size(18)
        
        ctx.move_to(0.8*cx,cy-size[1]/2-60); ctx.show_text('%s' % title)    
        ctx.stroke()
        
        # show comments
        ctx.set_source_rgb (0, 0, 0)
        ctx.set_line_width (0.5)
        ctx.select_font_face("Arial", 
                    cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
        ctx.set_font_size(12)
        
        ctx.move_to(cx-size[0]/2,cy+size[1]/2+20); ctx.show_text('%s' % comments)    
        ctx.stroke()
        
        if count:
            ctx.set_source_rgb (0, 0, 0)
            ctx.set_line_width (0.5)
            ctx.select_font_face("Arial", 
                    cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
            ctx.set_font_size(12)
        
            ctx.move_to(cx+size[0]/2-60,cy+size[1]/2+20)
            ctx.show_text('%s' % count)    
            ctx.stroke()
    
    
    
    surface.write_to_png(file_name)


def draw_Frame(ctx, width, height, cx, cy):
    
    # draw a frame
    ctx.set_source_rgb (0, 0, 0)
    ctx.set_line_width (4)
    ctx.move_to (cx-width/2.0,cy-height/2.0)
    ctx.line_to (cx+width/2.0,cy-height/2.0)
    ctx.line_to (cx+width/2.0,cy+height/2.0)
    ctx.line_to (cx-width/2.0,cy+height/2.0)
    ctx.line_to (cx-width/2.0,cy-height/2.0)
    ctx.stroke()
    
    #draw a horizontal axe  
    ctx.set_source_rgb (0, 0, 0)
    ctx.set_line_width (1)
    ctx.move_to (cx-width/2.0,cy)
    ctx.line_to (cx+width/2.0,cy)
    ctx.stroke()

def draw_Point(ctx, x, y, col, linewidth=2, r=5):
    ctx.set_source_rgb(col[0], col[1], col[2])
    ctx.set_line_width (linewidth)
    ctx.move_to(x + r, y)
    ctx.arc(x, y, r, 0, 2 * pi)    
    ctx.fill_preserve()
    ctx.set_source_rgb(1,1,1)
    ctx.stroke() 


def draw_Line(ctx, x1, y1, x2, y2, col, linewidth=1):        
    ctx.set_source_rgb(col[0], col[1], col[2])
    ctx.set_line_width (linewidth)
    ctx.move_to(x1, y1)
    ctx.line_to(x2, y2)        
    ctx.stroke()

def draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col):
    ctx.set_source_rgb(col[0], col[1], col[2])
    ctx.set_line_width (0)
    ctx.move_to(x1, y1)
    ctx.line_to(x2, y2)
    ctx.line_to(x3, y3)
    ctx.line_to(x4, y4)
    ctx.line_to(x1, y1)
    ctx.fill_preserve()
    ctx.set_source_rgb(1,1,1)
    ctx.stroke()
    
def recalc_coords(x, y, width, height, cx, cy):
    x1 = x*width/2.0 + cx
    y1 = y*height/2.0 + cy
    return x1, y1

def plot_density(density, ctx, width, heigth, cx, cy, cell_size, max_value):
    from plane import Plane    
    x0, y0 =  recalc_coords(1*2/360.0, 1/90.0-1, width, heigth, cx, cy)
    x1, y1 =  recalc_coords((1+cell_size)*2/360.0, (1+cell_size)/90.0-1,\
                                                          width, heigth, cx, cy)
    csx = (x1-x0)/2.0
    csy = (y1-y0)/2.0
        
    for pl in density:        
        pln = Plane(pl[0], pl[1])
        col = [1-pl[2]*1.0/max_value] * 3
        
        x,y = recalc_coords(pl[0]*2/360.0-1, pl[1]/90.0-1, width, heigth, cx, cy)
        y = y+csy
        x1,y1 = x+csx, y+csy
        x2,y2 = x+csx, y-csy
        x3,y3 = x-csx, y-csy
        x4,y4 = x-csx, y+csy
        draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col)
        draw_Point(ctx, x, y,col,0)
        x,y = recalc_coords(((((pl[0]*2/360.0)+1)%2)-1), (1 - pl[1]/90.0), width, heigth, cx, cy)
        y=y-csy
        x1,y1 = x+csx, y+csy
        x2,y2 = x+csx, y-csy
        x3,y3 = x-csx, y-csy
        x4,y4 = x-csx, y+csy
        draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col)
        draw_Point(ctx, x, y,col,0)
        '''
        pln1 = Plane(0, 0); pln2 = Plane(0, 0)
        pln3 = Plane(0, 0); pln4 = Plane(0, 0)        
        pln1.dir, pln1.dip = pln.dir + cell_size[0]/2.0, pln.dip + cell_size[1]/2.0
        pln2.dir, pln2.dip = pln.dir + cell_size[0]/2.0, pln.dip - cell_size[1]/2.0
        pln3.dir, pln3.dip = pln.dir - cell_size[0]/2.0, pln.dip - cell_size[1]/2.0
        pln4.dir, pln4.dip = pln.dir - cell_size[0]/2.0, pln.dip + cell_size[1]/2.0
        x1,y1 = recalc_coords((pln1.dir*2/360.0-1),  (pln1.dip/90.0-1), width, heigth, cx, cy)
        x2,y2 = recalc_coords((pln2.dir*2/360.0-1),  (pln2.dip/90.0-1), width, heigth, cx, cy)
        x3,y3 = recalc_coords((pln3.dir*2/360.0-1),  (pln3.dip/90.0-1), width, heigth, cx, cy)
        x4,y4 = recalc_coords((pln4.dir*2/360.0-1),  (pln4.dip/90.0-1), width, heigth, cx, cy)
        draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col)
        x1,y1 = recalc_coords(((((pln1.dir*2/360.0)+1)%2)-1), (1-pln1.dip/90.0), width, heigth, cx, cy)
        x2,y2 = recalc_coords(((((pln2.dir*2/360.0)+1)%2)-1), (1-pln2.dip/90.0), width, heigth, cx, cy)
        x3,y3 = recalc_coords(((((pln3.dir*2/360.0)+1)%2)-1), (1-pln3.dip/90.0), width, heigth, cx, cy)
        x4,y4 = recalc_coords(((((pln4.dir*2/360.0)+1)%2)-1), (1-pln4.dip/90.0), width, heigth, cx, cy)
        draw_Cell(ctx, x1, y1, x2, y2, x3, y3, x4, y4, col)
        '''
def plot_isolines(density_data, increment, width, height, cx, cy, ctx):
    from grid_plane import PlaneGrid
    from plane import Plane
    import isolines
    
    # prepare grid for doing isolines
    grid = PlaneGrid(incr=[int(increment), int(increment)])
    for pl in density_data:        
        grid.add(plane=Plane(pl[0], pl[1]), val=pl[2])
    density_grid = grid.returnGrid()
    
    # list of intervals
    intervals= [x/2.0 for x in range(0,200,1)]
    
    # doing isolines
    prepared_matrix=isolines.prepare_matrix(density_grid)    
    calculated_dots=isolines.calculate_dots(prepared_matrix,intervals)
    coords=isolines.calculate_coords(calculated_dots)
    
    # drawing
    lx=len(density_grid)
    ly=len(density_grid[0])    
    for cell in coords:        
        for edge in cell:
            # drawing up
            y1,x1 = (edge[1])/(ly)-1, (edge[2]-0.5)/(0.5*lx)-1
            y2,x2 = (edge[3])/(ly)-1, (edge[4]-0.5)/(0.5*lx)-1
            x1_,y1_ = recalc_coords(x1, y1, width, height, cx, cy)
            x2_,y2_ = recalc_coords(x2, y2, width, height, cx, cy)
            col = [0,0,0]
            draw_Line(ctx, x1_, y1_, x2_, y2_, col, linewidth=0.4) 
            
            # drawing down
            y1,x1 = 1-(edge[1])/(ly), (((edge[2]-0.5)/(0.5*lx)+1)%2)-1
            y2,x2 = 1-(edge[3])/(ly), (((edge[4]-0.5)/(0.5*lx)+1)%2)-1               
            x1_,y1_ = recalc_coords(x1, y1, width, height, cx, cy)
            x2_,y2_ = recalc_coords(x2, y2, width, height, cx, cy)
            # skip contours on a edge
            if sqrt((x2_-x1_)**2+(y2_-y1_)**2)>width-5*increment:                
                continue             
            col = [0,0,0]
            draw_Line(ctx, x1_, y1_, x2_, y2_, col, linewidth=0.4) 
